package ar.edu.sccs.model.wordnet;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.didion.jwnl.data.POS;

import org.apache.log4j.Logger;

import ar.edu.sccs.entities.Case;
import ar.edu.sccs.entities.Dimension;
import ar.edu.sccs.util.Constants;

public class SemanticModule {

	static Logger logger = Logger.getLogger(SemanticModule.class);

	public SemanticModule() {
		WordNetHelper.initialize(Constants.Resources.WORDNET_DICTIONARY);
	}

	public List<Case> getSemantic(Case targetCase) {
		List<String> listClassName = getDimensionSemantic(targetCase,
				Constants.Dimension.Class.NAME, POS.NOUN,
				Constants.Semantic.LIMIT_CLASS);
		List<String> listMethodObject = getDimensionSemantic(targetCase,
				Constants.Dimension.Method.OBJECT, POS.NOUN,
				Constants.Semantic.LIMIT_OBJECT);
		List<String> listMethodAction = getDimensionSemantic(targetCase,
				Constants.Dimension.Method.ACTION, POS.VERB,
				Constants.Semantic.LIMIT_ACTION);

		return getCombination(listClassName, listMethodObject, listMethodAction);
	}

	private List<String> getDimensionSemantic(Case targetCase,
			String dimensionName, POS wordType, int dimensionLimit) {
		logger.debug("SemanticModule.getDimensionSemantic '" + dimensionName
				+ "' for: " + targetCase.toString());
		List<String> listSemantic = new ArrayList<String>();

		Dimension dimension = targetCase.getDimensions().get(dimensionName);
		if (dimension != null) {
			if (dimension.isSemantic())
				listSemantic = WordNetHelper.getSynonymy((String) dimension
						.getValue(), wordType, dimensionLimit);
			else
				listSemantic.add((String) dimension.getValue());
		}

		return listSemantic;
	}

	// TODO Resolver secuencia de los FOR para evitar devolver listas vacias
	// cuando el primer elemento es vacio
	private List<Case> getCombination(List<String> listClassName,
			List<String> listMethodObject, List<String> listMethodAction) {
		List<Case> listCase = new ArrayList<Case>();

		if (listClassName == null || listMethodObject == null
				|| listMethodAction == null) {
			logger.fatal("SemanticModule.getCombination FATAL");
			return null;
		}

		if (listClassName.size() > 0 && listMethodObject.size() > 0
				&& listMethodAction.size() > 0)
			return getCombination(listClassName,
					Constants.Dimension.Class.NAME, listMethodObject,
					Constants.Dimension.Method.OBJECT, listMethodAction,
					Constants.Dimension.Method.ACTION);

		if (listClassName.size() > 0 && listMethodObject.size() > 0)
			return getCombination(listClassName,
					Constants.Dimension.Class.NAME, listMethodObject,
					Constants.Dimension.Method.OBJECT);

		if (listClassName.size() > 0 && listMethodAction.size() > 0)
			return getCombination(listClassName,
					Constants.Dimension.Class.NAME, listMethodAction,
					Constants.Dimension.Method.ACTION);

		if (listClassName.size() > 0)
			return getCombination(listClassName, Constants.Dimension.Class.NAME);

		if (listMethodObject.size() > 0)
			return getCombination(listMethodObject,
					Constants.Dimension.Method.OBJECT);

		if (listMethodAction.size() > 0)
			return getCombination(listMethodAction,
					Constants.Dimension.Method.ACTION);

		logger.info("SemanticModule.getCombination: Se generaron " + listCase.size() + " nuevos casos");
		return listCase;
	}

	private List<Case> getCombination(List<String> list1, String dim1,
			List<String> list2, String dim2, List<String> list3, String dim3) {
		List<Case> listCase = new ArrayList<Case>();

		for (String string1 : list1) {
			Map<String, Dimension> mapDim1 = new HashMap<String, Dimension>();
			mapDim1.put(dim1, new Dimension(string1));

			for (String string2 : list2) {
				Map<String, Dimension> mapDim2 = new HashMap<String, Dimension>();
				mapDim2.put(dim2, new Dimension(string2));

				for (String string3 : list3) {
					Map<String, Dimension> mapDim3 = new HashMap<String, Dimension>();
					mapDim3.put(dim3, new Dimension(string3));

					Case semanticCase = new Case();
					semanticCase.putDimension(mapDim1);
					semanticCase.putDimension(mapDim2);
					semanticCase.putDimension(mapDim3);

					listCase.add(semanticCase);
				}
			}
		}

		return listCase;
	}

	private List<Case> getCombination(List<String> list1, String dim1,
			List<String> list2, String dim2) {
		List<Case> listCase = new ArrayList<Case>();

		for (String string1 : list1) {
			Map<String, Dimension> mapDim1 = new HashMap<String, Dimension>();
			mapDim1.put(dim1, new Dimension(string1));

			for (String string2 : list2) {
				Map<String, Dimension> mapDim2 = new HashMap<String, Dimension>();
				mapDim2.put(dim2, new Dimension(string2));

				Case semanticCase = new Case();
				semanticCase.putDimension(mapDim1);
				semanticCase.putDimension(mapDim2);

				listCase.add(semanticCase);
			}
		}

		return listCase;
	}

	private List<Case> getCombination(List<String> list1, String dim1) {
		List<Case> listCase = new ArrayList<Case>();

		for (String string1 : list1) {
			Map<String, Dimension> mapDim1 = new HashMap<String, Dimension>();
			mapDim1.put(dim1, new Dimension(string1));

			Case semanticCase = new Case();
			semanticCase.putDimension(mapDim1);
			listCase.add(semanticCase);
		}

		return listCase;
	}
}
